package com.kingroad.auditproject.flow.serivce.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.kingroad.auditproject.common.enums.FlowStatusEnum;
import com.kingroad.auditproject.common.enums.OptTypeEnum;
import com.kingroad.auditproject.common.util.CommonUtil;
import com.kingroad.auditproject.common.util.Constants;
import com.kingroad.auditproject.extend.service.IXtOptInfoService;
import com.kingroad.auditproject.flow.api.SnakerFlowApi;
import com.kingroad.auditproject.flow.request.ApproveRequest;
import com.kingroad.auditproject.flow.request.StartFlowRequest;
import com.kingroad.auditproject.flow.ro.ExamineRo;
import com.kingroad.auditproject.flow.serivce.IFlowService;
import com.kingroad.auditproject.modules.auit.service.*;
import com.kuiren.common.easyui.RetData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author: jiaokunpeng
 * @Date: 2023/8/10 14:44
 * @Description: com.kingroad.auditproject.flow.serivce.impl
 * @version: 1.0
 */
@Service
public class FlowServiceImpl implements IFlowService {

    @Value("${flow.tenantId}")
    private String tenantId;

    @Autowired
    ISjPlanService sjPlanService;

    @Autowired
    ISjTeamApplyService sjTeamApplyService;

    @Autowired
    ISjImplementService sjImplementService;

    @Autowired
    ISjNoticeTzsService sjNoticeTzsService;

    @Autowired
    ISjCrimeService sjCrimeService;


    @Autowired
    private SnakerFlowApi snakerFlowApi;


    @Autowired
    private IXtOptInfoService xtOptInfoService;


    /**
     *
     SMALL_STEP_101("101", "审前准备-组建审计组"),
     SMALL_STEP_102("102", "审前准备-审计调查与分析"),
     SMALL_STEP_103("103", "审前准备-编制审计实施方案"),
     SMALL_STEP_104("104", "审前准备-送达审计通知书"),
     SMALL_STEP_201("201", "审计实施-进点会"),
     SMALL_STEP_202("202", "审计实施-现场取证"),
     SMALL_STEP_203("203", "审计实施-反馈会"),
     SMALL_STEP_204("204", "审计实施-编辑工作底稿"),
     SMALL_STEP_301("301", "审计结果应用-审计报告意见征求书"),
     SMALL_STEP_302("302", "审计结果应用通知书")

     * 通用审核
     * @param ro
     */
    @Override
    public RetData examine(ExamineRo ro) {
        String businessId = ro.getBusinessId();
        String othertoken = ro.getOtherToken();
        String taskId = ro.getTaskId();
        if (CommonUtil.isBlank(businessId)) {
            return RetData.error("业务主键不能为空！");
        }
        if (CommonUtil.isBlank(othertoken)) {
            return RetData.error("otherToken不能为空！");
        }
        if (CommonUtil.isBlank(taskId)) {
            return RetData.error("任务不能为空！");
        }
        switch (ro.getFlowNode()){
            case "100":
                // 计划立项申请
                return sjPlanService.examine(ro);
            case "101":
                //组建审计组
                return sjTeamApplyService.examine(ro);
            case "102":
                //审计调查与分析
                return RetData.succuess();
            case "103":
                //编制审计实施方案
                return sjImplementService.examine(ro);
            case "104":
                //送达审计通知书
                return sjNoticeTzsService.examine(ro);
            case "201":
                //进点会
                return null;
            case "202":
                //现场取证
                return null;
            case "203":
                //反馈会
                return null;
            case "204":
                //编辑工作底稿
                return null;
            case "301":
                //审计报告意见征求书
                return null;
            case "302":
                //审计结果应用通知书
                return null;
            default:break;
        }
        return RetData.error("未知的流程节点！");
    }




    /**
     * 流程提交
     * @param businessId  业务主键id
     * @param othertoken  流程访问token
     * @param processName 流程名称（一个流程一个固定名称）
     * @param nextUserId 下一步审批人 id
     * @param currentFlowNode 当前节点
     * @param flowJson 流程步骤
     * @param obj  当前流程对象
     * @param map 其他业务cabs
     * @return
     */
    public RetData startFlowNode(String businessId,String othertoken,String processName,String nextUserId,String currentFlowNode,String flowJson,Object obj, Map map){

        if (CommonUtil.isBlank(businessId)) {
            RetData.error("业务主键不能为空！");
        }

        if (CommonUtil.isBlank(othertoken)) {
            RetData.error("otherToken不能为空！");
        }

        if (CommonUtil.isBlank(processName)) {
            RetData.error("流程名称不能为空！");
        }

        if (CommonUtil.isBlank(nextUserId)) {
            RetData.error("下环节处理人不能为空！");
        }

        if (CommonUtil.isBlank(currentFlowNode)) {
            RetData.error("当前节点不能为空！");
        }

        if (CommonUtil.isBlank(flowJson)) {
            RetData.error("流程步骤不能为空！");
        }

        String userId = CommonUtil.getUserId();

        Map<String,String> headerMap = new HashMap<>();
        headerMap.put("othertoken",othertoken);  // 流程调用tokenId
        headerMap.put("tenantId",tenantId);

        StartFlowRequest startFlow = new StartFlowRequest();
        startFlow.setBusinessId(businessId);  //流程业务 id
        startFlow.setProcessName(processName);  //流程名称（一个流程一个固定名称）
        startFlow.setParams(JSON.parseObject(JSON.toJSONString(obj), Map.class)); //当前流程对象

        startFlow.getParams().put("submitterUser",userId); // 提交人
        startFlow.getParams().put("nextStepUser", nextUserId); //下一步审批人 id
        //启动流程
        JSONObject jsonObject = snakerFlowApi.startFlow(headerMap, startFlow);
        if (!Boolean.parseBoolean(jsonObject.getString("success")) || !"200".equals(jsonObject.getString("rtnCode"))){
           return RetData.error(Constants.submit_exception);
        }else{
            currentFlowNode = CommonUtil.isNull(currentFlowNode);
            // 插入审批日志
            Map<String,String> optMap = new HashMap<String,String>();
            map.put("flowType",CommonUtil.isNull(map.get("flowType")));//大类流程
            map.put("flowNode",CommonUtil.isNull(map.get("flowNode")));//小类流程
            map.put("sjProjectId",CommonUtil.isNull(map.get("sjProjectId")));//审计项目id
            map.put("currentFlowNode",currentFlowNode);// 当前流程节点
            xtOptInfoService.saveOpt(businessId,CommonUtil.isNull(map.get("flowNodeName")), OptTypeEnum.SUBMIT.getCode(),"",null,optMap);

            // 设置流程当前处理人和处理时间
            List<Map> mapList = JSONObject.parseArray(flowJson, Map.class);
            for (Map mapFlow : mapList) {
                if (currentFlowNode.equals(mapFlow.get("code"))){
                    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                    mapFlow.put("finishTime", formatter.format(LocalDateTime.now())); // 完成时间
                    mapFlow.put("finishUserId",userId); // 完成人
                }
            }
            Map<String,Object> rtnFlowMap =  new HashMap<>();
            rtnFlowMap.put("flowJson",JSON.toJSONString(mapList));

            return RetData.succuess(rtnFlowMap,Constants.submit_flow);
        }

    }



    /**
     * 流程审核
     * @param param  审核工作流通用
     * @param currentFlowNode 当前节点
     * @param flowJson 流程步骤
     * @param obj  当前流程对象
     * @param map 其他业务 endFlowNode、twoFlowNode、flowNodeName
     * @return
     */
    public RetData saveFlowNode(ExamineRo param,String currentFlowNode,String flowJson,Object obj, Map map){

        Map<String,Object> rtnFlowMap =  new HashMap<>(); // 返回参照

        String businessId = param.getBusinessId();
        String othertoken = param.getOtherToken();
        String taskId = param.getTaskId();
        String nextUserId = param.getNextUserId();

        if (CommonUtil.isBlank(businessId)) {
            RetData.error("业务主键不能为空！");
        }

        if (CommonUtil.isBlank(othertoken)) {
            RetData.error("otherToken不能为空！");
        }

        if (CommonUtil.isBlank(taskId)) {
            RetData.error("任务不能为空！");
        }

        if (CommonUtil.isBlank(currentFlowNode)) {
            RetData.error("当前节点不能为空！");
        }

        if (CommonUtil.isBlank(flowJson)) {
            RetData.error("流程步骤不能为空！");
        }

        String userId = CommonUtil.getUserId();

        currentFlowNode = CommonUtil.isNull(currentFlowNode); // 当前单据节点
        String preFlowNode = "0";   // 上一个节点
        String nextFlowNode = "-1";  // 下一个节点
        if (!currentFlowNode.equals("")){
            preFlowNode = CommonUtil.isNull(Integer.parseInt(currentFlowNode) - 1);
            nextFlowNode = CommonUtil.isNull(Integer.parseInt(currentFlowNode) + 1);
        }

        String endFlowNode = CommonUtil.isNull(map.get("endFlowNode")); // 最后一个节点
        String twoFlowNode = CommonUtil.isNull(map.get("twoFlowNode")); // 提交之后的下一个节点
        String nextStepUser = CommonUtil.isNull(nextUserId);  // 下一个审核人
        String updateFlowStatus = FlowStatusEnum.IN_APPROVAL.getCode();  // 单据要修改的状态
        String updateFlowNode = "0";  // 单据要修改的节点
        flowJson =  CommonUtil.isNull(flowJson); // 业务流程josn


        String paramFlowStatus = param.getFlowStatus();  // 审计结论:同意、驳回
        String optType = ""; // 日志操作类型



        if(!currentFlowNode.equals(endFlowNode) && FlowStatusEnum.PASS.getCode().equals(paramFlowStatus)){
            // 审核通过，并且节点不是最后一个
            if(nextStepUser.equals("")){
                RetData.error("下一个审核人不能为空！");
            }
        }

        //修改flowJson
        // 设置流程当前处理人和处理时间
        List<Map> mapList = JSONObject.parseArray(flowJson, Map.class);
        for (Map mapFlow : mapList) {
            if (currentFlowNode.equals(mapFlow.get("code"))){
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                mapFlow.put("finishTime", formatter.format(LocalDateTime.now())); // 完成时间
                mapFlow.put("finishUserId",userId); // 完成人
            }
        }
        rtnFlowMap.put("flowJson",JSON.toJSONString(mapList));


        //-----------------------设置单据状态

        if(currentFlowNode.equals(endFlowNode) && FlowStatusEnum.PASS.getCode().equals(paramFlowStatus)){
            updateFlowStatus = FlowStatusEnum.PASS.getCode(); // 审核通过 ： 最后节点并且审核通过
        }
        if(currentFlowNode.equals(twoFlowNode) && FlowStatusEnum.REJECT.getCode().equals(paramFlowStatus)){
            updateFlowStatus = FlowStatusEnum.REJECT.getCode(); // 审核驳回：审核意见退回，并且倒数第二个节点
        }

        rtnFlowMap.put("updateFlowStatus",updateFlowStatus);


        //-----------------------设置单据流程节点

        // 如果审核通过
        if( FlowStatusEnum.PASS.getCode().equals(paramFlowStatus)){
            updateFlowNode = nextFlowNode;
        }
        // 如果审核驳回
        if( FlowStatusEnum.REJECT.getCode().equals(paramFlowStatus)){
            updateFlowNode = preFlowNode;
        }
        // 审核通过最后的节点为空
        if(updateFlowStatus.equals(FlowStatusEnum.PASS.getCode())){
            updateFlowNode = "";
            nextStepUser = "";
        }

        rtnFlowMap.put("updateFlowNode",updateFlowNode);


        // ----------------下一个处理人
        if( FlowStatusEnum.REJECT.getCode().equals(paramFlowStatus)){
            // 根据上一个节点找到最后的处理人
            for (Map mapFlow : mapList) {
                if (preFlowNode.equals(mapFlow.get("code"))){
                    nextStepUser =  CommonUtil.isNull(mapFlow.get("finishUserId"));
                    if(nextStepUser.equals("")){
                        RetData.error("上一个审核人不能为空！");
                    }
                }
            }
        }

        //组建工作流入参  - 审核
        Map<String,String> headerMap = new HashMap<>();
        headerMap.put("othertoken", othertoken);
        headerMap.put("tenantId",tenantId);
        ApproveRequest approveRequest = new ApproveRequest();
        approveRequest.setTaskId(taskId); //待办任务 id
        approveRequest.setAuditMessage(param.getOpinion());  //审批意见
        approveRequest.setParams(JSON.parseObject(JSON.toJSONString(obj)).getInnerMap());  //业务对象序列化
        approveRequest.getParams().put("nextStepUser",nextStepUser); // 下一步审批人 id
        approveRequest.getParams().put("isEnd", false);
        if(CommonUtil.isNull(param.getIsEnd()).equals("1")){
            approveRequest.getParams().put("isEnd", true);    // 审计计划立项流程分支
        }

        JSONObject jsonObject = null;
        if (FlowStatusEnum.PASS.getCode().equals(paramFlowStatus)) {
            // 审核通过
            optType = OptTypeEnum.AGREE.getCode();
            jsonObject = snakerFlowApi.examine(headerMap, approveRequest);
        } else if (FlowStatusEnum.REJECT.getCode().equals(paramFlowStatus)) {
            // 审核拒绝
            optType = OptTypeEnum.RETURN.getCode();
            jsonObject = snakerFlowApi.reject(headerMap, approveRequest);
        }

        if (!Boolean.parseBoolean(jsonObject.getString("success")) || !"200".equals(jsonObject.getString("rtnCode"))){
            return RetData.error(Constants.submit_exception);
        }else{
            // 插入日志
            xtOptInfoService.saveOpt(businessId,CommonUtil.isNull(map.get("flowNodeName")),optType,param.getOpinion(),null,null);
            return RetData.succuess(rtnFlowMap,Constants.submit_flow);
        }
    }


}
